/*
 * Copyright (c)  2017, ueboot.com
 * All rights reserved.
 * 2017-10-14 21:04:14
 */
package com.ueboot.weishop.admin.controller.activity;

import com.ueboot.core.exception.BusinessException;
import com.ueboot.core.http.response.Response;
import com.ueboot.core.utils.DateUtils;
import com.ueboot.weishop.admin.controller.activity.vo.*;
import com.ueboot.weishop.entity.activity.ActivityAttrEntity;
import com.ueboot.weishop.entity.activity.ActivityEntity;
import com.ueboot.weishop.entity.goods.GoodsInfoEntity;
import com.ueboot.weishop.service.activity.ActivityAttrService;
import com.ueboot.weishop.service.activity.ActivityService;
import com.ueboot.weishop.service.cache.ActivityCountDTO;
import com.ueboot.weishop.service.cache.CacheService;
import com.ueboot.weishop.service.goods.GoodsInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;


/**
 * Created by Neel  on 2017-10-14 21:04:14.
 * 活动管理相关接口
 *
 * @author yangkui
 * @since 2.0 by autocode
 */
@Slf4j
@RestController
@RequestMapping(value = "/activities")
public class ActivityController {

	@Autowired
	private ActivityService activityService;

	@Autowired
	private ActivityAttrService activityAttrService;

	@Autowired
	private GoodsInfoService goodsInfoService;

	@Autowired
	private CacheService cacheService;

	@Autowired
	private RedisTemplate redisTemplate;

	@RequiresPermissions("activities:read")
	@RequestMapping(value = "/findActivityCount", method = RequestMethod.POST)
	public Response<ActivityCountResp> findActivityCount(@RequestBody(required = true) ActivityCountReq req) {
		ActivityCountDTO dto = cacheService.countActInfo(req.getActSn());
		//在线人数
		Set<String> sets = redisTemplate.keys("spring:session:weishop:sessions:*");
		ActivityCountResp resp = new ActivityCountResp();
		BeanUtils.copyProperties(dto, resp);
		resp.setOnlineCount(sets.size());
		return new Response<>(resp);
	}


	@RequiresPermissions("activities:read")
	@RequestMapping(value = "/page", method = RequestMethod.POST)
	public Response<Page<ActivityResp>> page(@PageableDefault(value = 15, sort = {"id"}, direction = Sort.Direction.DESC)
			                                         Pageable pageable, @RequestBody(required = false) ActivityFindReq req) {
		Page<ActivityEntity> entities = activityService.findBy(pageable);
		Page<ActivityResp> body = entities.map(entity -> {
			ActivityResp resp = new ActivityResp();
			BeanUtils.copyProperties(entity, resp);
			resp.setStartTime(DateUtils.format(entity.getStartTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
			resp.setEndTime(DateUtils.format(entity.getEndTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
			return resp;
		});

		return new Response<>(body);
	}

	/**
	 * 秒杀活动列表查询
	 *
	 * @param pageable
	 * @param req
	 * @return
	 */
	@RequiresPermissions("activities:read")
	@RequestMapping(value = "/seckillPage", method = RequestMethod.POST)
	public Response<Page<ActivitySecKillResp>> seckillPage(@PageableDefault(value = 15, sort = {"id"}, direction = Sort.Direction.DESC)
			                                                       Pageable pageable, @RequestBody(required = false) ActivityFindReq req) {
		Page<ActivityEntity> entities = activityService.findByTypeOrderByStartTimeAsc(pageable, ActivityEntity.TYPE_SEC_KILL);
		Page<ActivitySecKillResp> body = entities.map(entity -> {
			ActivitySecKillResp resp = new ActivitySecKillResp();
			assembleResp(resp, entity);
			List<GoodsInfoEntity> gs = goodsInfoService.findByActivityId(entity.getId());
			if (gs != null && gs.size() > 0) {
				GoodsInfoEntity goodsInfo = gs.get(0);
				if (goodsInfo != null) {
					resp.setGoodsInfoMainImgUrl(goodsInfo.getMainImgUrl().split(GoodsInfoEntity.IMG_URL_SPLIT_CHAR)[0]);
					resp.setGoodsInfoName(goodsInfo.getName());
				}
			}
			resp.setSeckillPrice(resp.getSeckillPrice() / 100);
			return resp;
		});

		return new Response<>(body);
	}


	/**
	 * 众筹活动列表查询
	 *
	 * @param pageable
	 * @return
	 */
	@RequiresPermissions("activities:read")
	@RequestMapping(value = "/crowPage", method = RequestMethod.POST)
	public Response<Page<ActivityCrowResp>> crowPage(@PageableDefault(value = 15, sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable) {
		Page<ActivityEntity> entities = activityService.findByTypeOrderByStartTimeAsc(pageable, ActivityEntity.TYPE_CROW);
		Page<ActivityCrowResp> body = entities.map(entity -> {
			ActivityCrowResp resp = new ActivityCrowResp();
			assembleResp(resp, entity);
			List<GoodsInfoEntity> gs = goodsInfoService.findByActivityId(entity.getId());
			if (gs != null && gs.size() > 0) {
				GoodsInfoEntity goodsInfo = gs.get(0);
				if (goodsInfo != null) {
					resp.setGoodsInfoName(goodsInfo.getName());
					resp.setGoodsInfoMainImgUrl(goodsInfo.getMainImgUrl().split(GoodsInfoEntity.IMG_URL_SPLIT_CHAR)[0]);
				}
			}
			resp.setCrowUnitPrice(entity.getCrowUnitPrice() / 100);
			return resp;
		});

		return new Response<>(body);
	}


	/**
	 * 代金券活动列表查询
	 *
	 * @param pageable
	 * @return
	 */
	@RequiresPermissions("activities:read")
	@RequestMapping(value = "/couponPage", method = RequestMethod.POST)
	public Response<Page<ActivityCouponResp>> couponPage(@PageableDefault(value = 15, sort = {"id"}, direction = Sort.Direction.DESC) Pageable pageable) {
		Page<ActivityEntity> entities = activityService.findByTypeOrderByStartTimeAsc(pageable, ActivityEntity.TYPE_COUPON);
		Page<ActivityCouponResp> body = entities.map(entity -> {
			ActivityCouponResp resp = new ActivityCouponResp();
			assembleResp(resp, entity);

			ActivityAttrEntity couponAmountAttr = null;
			ActivityAttrEntity couponProjectCodeAttr = null;
			ActivityAttrEntity couponActualCountAttr = null;
			ActivityAttrEntity couponCustomerTypeAttr = null;
			ActivityAttrEntity couponStartDateAttr = null;
			ActivityAttrEntity couponEndDateAttr = null;
			log.info("sn:{}",entity.getSn());
			List<ActivityAttrEntity> activityAttrs = activityAttrService.findBySnNoCache(entity.getSn());
			log.info("###sn:{},activityAttrs size:{}",entity.getSn(),activityAttrs.size());
			for (ActivityAttrEntity attrEntity : activityAttrs) {
				if ("couponAmount".equals(attrEntity.getKeyName())) {
					couponAmountAttr = attrEntity;
					continue;
				}
				if ("couponProjectCode".equals(attrEntity.getKeyName())) {
					couponProjectCodeAttr = attrEntity;
					continue;
				}
				if ("couponActualCount".equals(attrEntity.getKeyName())) {
					couponActualCountAttr = attrEntity;
					continue;
				}
				if ("couponCustomerType".equals(attrEntity.getKeyName())) {
					couponCustomerTypeAttr = attrEntity;
					continue;
				}
				if ("couponStartDate".equals(attrEntity.getKeyName())) {
					couponStartDateAttr = attrEntity;
					continue;
				}
				if ("couponEndDate".equals(attrEntity.getKeyName())) {
					couponEndDateAttr = attrEntity;
					continue;
				}
			}

			resp.setCouponAmount(couponAmountAttr == null || couponAmountAttr.getValue() == null ? 0 : Integer.parseInt(couponAmountAttr.getValue()) / 100);
			resp.setCouponProjectCode(couponProjectCodeAttr == null ? null : couponProjectCodeAttr.getValue());
			resp.setCouponActualCount(couponActualCountAttr == null || couponActualCountAttr.getValue() == null ? 0 : Integer.parseInt(couponActualCountAttr.getValue()));
			resp.setCouponCustomerType(couponCustomerTypeAttr == null ? null : couponCustomerTypeAttr.getValue());
			resp.setCouponStartDate(couponStartDateAttr == null ? null : couponStartDateAttr.getValue());
			resp.setCouponEndDate(couponEndDateAttr == null ? null : couponEndDateAttr.getValue());


			log.info("couponAmountAttr: {}, couponProjectCodeAttr: {} couponActualCountAttr: {} couponCustomerTypeAttr: {} couponStartDateAttr: {}, couponEndDateAttr: {}", couponAmountAttr, couponProjectCodeAttr, couponActualCountAttr, couponCustomerTypeAttr, couponStartDateAttr, couponEndDateAttr);
			//缓存代金券领取数量的key
			if (couponCustomerTypeAttr != null) {
				String countKey = entity.getGroupCode() + "|" + couponCustomerTypeAttr.getValue();
				Integer buyCount = cacheService.getAlreadyBuyCount(entity.getSn(), countKey);

				resp.setCouponDrawCount(buyCount == null ? 0 : buyCount.intValue());
			}

			return resp;
		});

		return new Response<>(body);
	}

	/**
	 * 限时折扣活动列表查询
	 *
	 * @param pageable
	 * @param req
	 * @return
	 */
	@RequiresPermissions("activities:read")
	@RequestMapping(value = "/discountPage", method = RequestMethod.POST)
	public Response<Page<ActivityDiscountResp>> discountPage(@PageableDefault(value = 15, sort = {"id"}, direction = Sort.Direction.DESC)
			                                                         Pageable pageable, @RequestBody(required = false) ActivityFindReq req) {
		Page<ActivityEntity> entities = activityService.findByTypeOrderByStartTimeAsc(pageable, ActivityEntity.TYPE_DISCOUNT);
		Page<ActivityDiscountResp> body = entities.map(entity -> {
			ActivityDiscountResp resp = new ActivityDiscountResp();
			assembleResp(resp, entity);
			//折扣值与直接减去金额为二选一
			resp.setDiscountValue(entity.getDiscountValue());
			// 直接减去的金额(单位分)变为元
			resp.setDiscountMinusPrice(entity.getDiscountMinusPrice() != null ? entity.getDiscountMinusPrice() / 100 : null);
			// 直接减去的金额(单位分)变为元
			resp.setDiscountOriginPrice(entity.getDiscountOriginPrice() != null ? entity.getDiscountOriginPrice() / 100 : null);
			return resp;
		});
		return new Response<>(body);
	}

	private void assembleResp(ActivityResp resp, ActivityEntity entity) {
		BeanUtils.copyProperties(entity, resp);
		resp.setStartTime(DateUtils.format(entity.getStartTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
		resp.setEndTime(DateUtils.format(entity.getEndTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
	}

	/**
	 * 保存活动信息
	 */
	@RequiresPermissions("activities:save")
	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public Response<Void> save(@RequestBody ActivityReq req) {
		ActivityEntity entity = null;
		if (req.getId() == null) {
			entity = new ActivityEntity();
		} else {
			entity = activityService.get(req.getId());
		}
		BeanUtils.copyProperties(req, entity);
		if (ActivityEntity.TYPE_SEC_KILL.equals(req.getType())) {
			//秒杀价格*100
			entity.setSeckillPrice(entity.getSeckillPrice() * 100);
			activityService.saveActivity(entity, req.getGoodsInfoId());

		} else if (ActivityEntity.TYPE_DISCOUNT.equals(req.getType())) {
			if (entity.getDiscountMinusPrice() != null) {
				//直接减去的金额*100
				entity.setDiscountMinusPrice(entity.getDiscountMinusPrice() * 100);
			}
			if (entity.getDiscountOriginPrice() != null) {
				//直接减去的金额*100
				entity.setDiscountOriginPrice(entity.getDiscountOriginPrice() * 100);
			}
			activityService.save(entity);
		} else if (ActivityEntity.TYPE_CROW.equals(req.getType())) {
			if (entity.getCrowUnitPrice() != null) {
				//众筹单价*100
				entity.setCrowUnitPrice(entity.getCrowUnitPrice() * 100);
				if (entity.getPeriodNum() == null) {
					entity.setPeriodNum(cacheService.incrPeriodNum(entity.getSn()));
				}
			}
			activityService.saveActivity(entity, req.getGoodsInfoId());
		} else if (ActivityEntity.TYPE_COUPON.equals(req.getType())) {
			List<ActivityAttrEntity> attrList = new ArrayList<>();

			ActivityAttrEntity couponAmountAttr = null;
			ActivityAttrEntity couponProjectCodeAttr = null;
			ActivityAttrEntity couponActualCountAttr = null;
			ActivityAttrEntity couponCustomerTypeAttr = null;
			ActivityAttrEntity couponStartDateAttr = null;
			ActivityAttrEntity couponEndDateAttr = null;


			if (req.getId() != null) {
				List<ActivityAttrEntity> activityAttrs = activityAttrService.findBySnNoCache(entity.getSn());

				for (ActivityAttrEntity attrEntity : activityAttrs) {
					if ("couponAmount".equals(attrEntity.getKeyName())) {
						couponAmountAttr = attrEntity;
						continue;
					}
					if ("couponProjectCode".equals(attrEntity.getKeyName())) {
						couponProjectCodeAttr = attrEntity;
						continue;
					}
					if ("couponActualCount".equals(attrEntity.getKeyName())) {
						couponActualCountAttr = attrEntity;
						continue;
					}
					if ("couponCustomerType".equals(attrEntity.getKeyName())) {
						couponCustomerTypeAttr = attrEntity;
						continue;
					}
					if ("couponStartDate".equals(attrEntity.getKeyName())) {
						couponStartDateAttr = attrEntity;
						continue;
					}
					if ("couponEndDate".equals(attrEntity.getKeyName())) {
						couponEndDateAttr = attrEntity;
						continue;
					}
				}
			}
			if (req.getId() == null) {
				entity.setSn(DateUtils.getCurrentDateTime());
			}
			couponAmountAttr = couponAmountAttr == null ? new ActivityAttrEntity() : couponAmountAttr;
			couponAmountAttr.setActivity(entity);
			couponAmountAttr.setSn(entity.getSn());
			couponAmountAttr.setKeyName("couponAmount");
			couponAmountAttr.setName("每张代金券金额");
			couponAmountAttr.setValue(String.valueOf(req.getCouponAmount() * 100));

			attrList.add(couponAmountAttr);


			couponProjectCodeAttr = couponProjectCodeAttr == null ? new ActivityAttrEntity() : couponProjectCodeAttr;
			couponProjectCodeAttr.setActivity(entity);
			couponProjectCodeAttr.setSn(entity.getSn());
			couponProjectCodeAttr.setKeyName("couponProjectCode");
			couponProjectCodeAttr.setName("代金券项目编号");
			couponProjectCodeAttr.setValue(req.getCouponProjectCode());

			attrList.add(couponProjectCodeAttr);


			couponActualCountAttr = couponActualCountAttr == null ? new ActivityAttrEntity() : couponActualCountAttr;
			couponActualCountAttr.setActivity(entity);
			couponActualCountAttr.setSn(entity.getSn());
			couponActualCountAttr.setKeyName("couponActualCount");
			couponActualCountAttr.setName("每日发放数量");
			couponActualCountAttr.setValue(String.valueOf(req.getCouponActualCount()));

			attrList.add(couponActualCountAttr);


			couponCustomerTypeAttr = couponCustomerTypeAttr == null ? new ActivityAttrEntity() : couponCustomerTypeAttr;
			couponCustomerTypeAttr.setActivity(entity);
			couponCustomerTypeAttr.setSn(entity.getSn());
			couponCustomerTypeAttr.setKeyName("couponCustomerType");
			couponCustomerTypeAttr.setName("针对客户类别");
			couponCustomerTypeAttr.setValue(req.getCouponCustomerType());

			attrList.add(couponCustomerTypeAttr);

			couponStartDateAttr = couponStartDateAttr == null ? new ActivityAttrEntity() : couponStartDateAttr;
			couponStartDateAttr.setActivity(entity);
			couponStartDateAttr.setSn(entity.getSn());
			couponStartDateAttr.setKeyName("couponStartDate");
			couponStartDateAttr.setName("代金券使用开始日期");
			couponStartDateAttr.setValue(DateUtils.format(req.getCouponStartDate(), DateUtils.FORMAT_DATE_DEFAULT));

			attrList.add(couponStartDateAttr);

			couponEndDateAttr = couponEndDateAttr == null ? new ActivityAttrEntity() : couponEndDateAttr;
			couponEndDateAttr.setActivity(entity);
			couponEndDateAttr.setSn(entity.getSn());
			couponEndDateAttr.setKeyName("couponEndDate");
			couponEndDateAttr.setName("代金券使用截止日期");
			couponEndDateAttr.setValue(DateUtils.format(req.getCouponEndDate(), DateUtils.FORMAT_DATE_DEFAULT));

			attrList.add(couponEndDateAttr);


			activityService.saveActivity(entity, attrList);


		}
		return new Response<>();
	}

	/**
	 * 关联活动下的商品列表数据
	 *
	 * @param req
	 * @return
	 */
	@RequiresPermissions("activities:save")
	@RequestMapping(value = "/goods/save", method = RequestMethod.POST)
	public Response<Void> saveActivityGoods(@RequestBody ActivityGoodsReq req) {
		if (req.getId() == null) {
			throw new BusinessException("请选择活动");
		}
		ActivityEntity entity = activityService.get(req.getId());
		if (entity == null) {
			throw new BusinessException("活动不存在或已被删除");
		}
		if (req.getGoodsIds() == null || req.getGoodsIds().length <= 0) {
			throw new BusinessException("请选择商品");
		}

		activityService.saveActivityGoods(entity, req.getGoodsIds());

		return new Response<>();
	}


	@RequiresPermissions("activities:delete")
	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	public Response<Void> delete(Long[] id) {
		for (Long aLong : id) {
			activityService.deleteActivity(aLong);
		}
		return new Response<>();
	}

	@RequiresPermissions("goodsInfo:delete")
	@RequestMapping(value = "/clearCache", method = RequestMethod.POST)
	public Response<Void> clearCache() {
		activityService.clearActivityCache();
		return new Response<>();
	}

	@RequiresPermissions("activities:read")
	@RequestMapping(value = "/{id}", method = RequestMethod.POST)
	public Response<ActivityResp> get(@PathVariable Long id) {
		ActivityEntity entity = activityService.get(id);
		ActivityResp resp = new ActivityResp();
		BeanUtils.copyProperties(entity, resp);
		resp.setStartTime(DateUtils.format(entity.getStartTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
		resp.setEndTime(DateUtils.format(entity.getEndTime(), DateUtils.FORMAT_DATE_TIME_DEFAULT));
		return new Response<>(resp);
	}

}
